package com.voyage.oauth.config;

import com.voyage.oauth.service.VoyageUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.sql.DataSource;

/**
 * @Author: kangb on 2021/10/30 21:59
 * @Description: Oauth2.0的配置
 */

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {


    private final AuthenticationManager authenticationManager;
    //    private final TokenStore redisTokenStore;
    private final TokenStore jwtTokenStore;
    private final VoyageUserDetailsService voyageUserDetailsService;
    private final PasswordEncoder passwordEncoder;
    private final DataSource dataSource;
    private final JwtAccessTokenConverter jwtAccessTokenConverter;

    @Autowired
    public AuthorizationServerConfig(AuthenticationManager authenticationManager,
                                     TokenStore jwtTokenStore,
                                     VoyageUserDetailsService voyageUserDetailsService,
                                     PasswordEncoder passwordEncoder,
                                     DataSource dataSource,
                                     JwtAccessTokenConverter jwtAccessTokenConverter) {
        this.authenticationManager = authenticationManager;
        this.jwtTokenStore = jwtTokenStore;
        this.voyageUserDetailsService = voyageUserDetailsService;
        this.passwordEncoder = passwordEncoder;
        this.dataSource = dataSource;
        this.jwtAccessTokenConverter = jwtAccessTokenConverter;
    }

    /**
     * 使用redis保存token
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //redis模式
//        endpoints.authenticationManager(authenticationManager)
//                .userDetailsService(voyageUserDetailsService)
//                .tokenStore(redisTokenStore);
        // jwt模式
        endpoints.tokenStore(jwtTokenStore)
                .accessTokenConverter(jwtAccessTokenConverter)
                .userDetailsService(voyageUserDetailsService)
                .authenticationManager(authenticationManager);
    }

    /**
     * 配置授权方式及参数
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 基于内存模式
//        clients.inMemory().withClient("voyage-client")
//                .secret(passwordEncoder.encode("voyage-secret"))
//                .authorizedGrantTypes("refresh_token", "authorization_code", "password")
//                .accessTokenValiditySeconds(7200)
//                .redirectUris("http://www.baidu.com")
//                .scopes("all");
        // 数据库获取方式
        JdbcClientDetailsServiceBuilder jcsb = clients.jdbc(dataSource);
        jcsb.passwordEncoder(passwordEncoder);
    }

    /**
     * 设置授权方式
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
        security.checkTokenAccess("isAuthenticated()");
        security.tokenKeyAccess("isAuthenticated()");
    }
}
